/****************************************************************************/
/***                                                                      ***/
/***   (C) 2012-2014 Dierk Ohlerich et al., all rights reserved.          ***/
/***                                                                      ***/
/***   Released under BSD 2 clause license, see LICENSE.TXT               ***/
/***                                                                      ***/
/****************************************************************************/

mtrl TesselateShader 
{
  permute Wireframe;

  struct ia2vs
  {
    float3 pos : POSITION;
    float3 norm : NORMAL;
    float2 uv0 : TEXCOORD0;
  };

  struct vs2hs
  {
    float3 pos : POSITION;
    float3 norm : NORMAL;
    float2 uv0 : TEXCOORD0;
  };

  struct tess
  {
    float edges[3] : SV_TessFactor;
    float inside : SV_InsideTessFactor;
  };

  struct hs2ds
  {
    float3 pos : POSITION;
    float3 norm : NORMAL;
    float2 uv0 : TEXCOORD0;
  };

  struct ds2gs
  {
    float4 tpos : POSITION;
    float4 color : COLOR0;
    float2 uv0 : TEXCOORD0;
  };

  struct gs2ps
  {
    float4 color : COLOR0;
    float2 uv0 : TEXCOORD0;
    float4 tpos : SV_Position;
  };

  cbuffer cbh0 : hs(0) : register(0)
  {
    row_major float4x4 MS2SS;
    float3 txx;
    float Quality;
  };

  cbuffer cbd0 : ds(0) : register(0)
  {
    row_major float4x4 MS2SS;
    float3 ldir;
  };
  
  vs hlsl5
  {
    void main(in ia2vs i,out vs2hs o)
    {
      o.pos = i.pos;
      o.norm = i.norm;
      o.uv0 = i.uv0;
    }
  };

  hs hlsl5
  {
    float tessfactor(float3 p0,float3 p1)
    {
      float3 center = (p0+p1)*0.5;
      float radius = length(p0-p1)*0.5;

      float4 r0 = mul(MS2SS,float4(center,1));
      center += radius*txx;
      float4 r1 = mul(MS2SS,float4(center,1));
      return length(r0.xy/r0.w - r1.xy/r1.w)*Quality;
    } 

    void mainc(in InputPatch<vs2hs,3> i,out tess o)
    { 
      o.edges[0] = tessfactor(i[1].pos,i[2].pos);
      o.edges[1] = tessfactor(i[2].pos,i[0].pos);
      o.edges[2] = tessfactor(i[0].pos,i[1].pos);
      o.inside = (o.edges[0]+o.edges[1]+o.edges[2])/3;
    }
    [domain("tri")]
    [partitioning("fractional_odd")]
    [outputtopology("triangle_cw")]
    [outputcontrolpoints(3)]
    [patchconstantfunc("mainc")]
    [maxtessfactor(9.0)]
    hs2ds main(in InputPatch<vs2hs,3> i,
               uint id : SV_OutputControlPointID)
    {
      hs2ds o;
      o.pos = i[id].pos;
      o.norm = i[id].norm;
      o.uv0 = i[id].uv0;
      return o;
    }
  };

  ds hlsl5 
  {
    [domain("tri")]
    void main(in tess c,in OutputPatch<hs2ds,3> i,
              in float3 bc : SV_DomainLocation,
              out ds2gs o)
    {
      float3 pos,norm;
      pos    = i[0].pos *bc.x + i[1].pos *bc.y + i[2].pos *bc.z;
      norm   = i[0].norm*bc.x + i[1].norm*bc.y + i[2].norm*bc.z;
      o.uv0  = i[0].uv0 *bc.x + i[1].uv0 *bc.y + i[2].uv0 *bc.z;

      norm = normalize(norm);
      o.color.xyz = saturate(dot(norm,ldir)*0.75+0.25);
      o.color.w = 1;
      o.tpos = mul(MS2SS,float4(pos,1));
    }
  };


  gs hlsl5
  {
    pif(Wireframe)
    {
      [maxvertexcount(4)]
      void main(triangle ds2gs i[3],inout LineStream<gs2ps> os)
      {
        gs2ps o;

        for(uint n=0;n<4;n++)
        {
          o.tpos = i[n%3].tpos;
          o.color = i[n%3].color;
          o.uv0 = i[n%3].uv0;
          os.Append(o);
        }
      }
    }
    pif(!Wireframe)
    {
      [maxvertexcount(3)]
      void main(triangle ds2gs i[3],inout TriangleStream<gs2ps> os)
      {
        gs2ps o;

        for(uint n=0;n<3;n++)
        {
          o.tpos = i[n].tpos;
          o.color = i[n].color;
          o.uv0 = i[n].uv0;
          os.Append(o);
        }
      }
    }
  };

  ps hlsl5
  {
    void main(in gs2ps i,out float4 r:SV_Target)
    {
      r = i.color;
    }
  };
} 

/****************************************************************************/
